# 编写自定义文件存储系统
# 如果您需要提供自定义文件存储 - 一个常见示例是将文件存储在某个远程系统上 - 您可以通过定义自定义存储类来实现
# 您需要按照以下步骤操作：

from fdfs_client.client import Fdfs_client
from django.utils.deconstruct import deconstructible


# 1.您的自定义存储系统必须是以下子类 django.core.files.storage.Storage：
# 4您的存储类必须是可解构的， 以便在迁移中的字段上使用时可以对其进行序列化。只要您的字段具有可自行序列化的参数
# 就 可以使用 django.utils.deconstruct.deconstructible类装饰器（这就是Django在FileSystemStorage上使用的
from django.core.files.storage import Storage
from django.conf import settings

@deconstructible
class FastDFSStorage(Storage):

    """
    2.Django必须能够在没有任何参数的情况下实例化您的存储系统。这意味着任何设置都应该来自django.conf.settings
    """
    def __init__(self,path=None,ip=None):

        if path is None:
            path = settings.FDFS_CLIENT_CONF
        self.config_path = path

        if ip is None:

            ip = settings.FDFS_URL
        self.ip = ip



    # 3.您的存储类必须实现_open()和_save() 方法以及适用于您的存储类的任何其他方法

    # 打开图片.是使用FastDFS来实现的,所以可以不用写此方法
    def _open(self, name, mode='rb'):

        pass

    # 保存,必须实现
    def _save(self, name, content, max_length=None):

        # 1.name 是一个文件名,不是一个路径
        # 2.content 是上传的内容,我们可以通过content.read()来获取文件的二进制数据

        # 创建fastdfs的客户端,加载配置文件
        # client = Fdfs_client('utils/fastdfs/client.conf')
        client = Fdfs_client(self.config_path)
        # 上传文件
        file_data = content.read()  # 获取文件的二进制数据

        # buffer 上传二进制数据,它会将上传结果返回
        result = client.upload_appender_by_buffer(file_data)

        # 3.判断上传的状态,如果上传成功 ,我们需要获取
        # {'Remote file_id': 'group1/M00/00/02/wKjlhVtnotmAInopAAUJgyD1NQ4381.jpg',
        #  'Group name': 'group1',
        # 'Uploaded size': '322.00KB',
        # 'Local file name': '/home/python/Desktop/images/1.jpg',
        # 'Status': 'Upload successed.', "
        # 'Storage IP': '192.168.229.133'}

        if result.get('Status') == "Upload successed.":
            # 上传成功
            return result.get("Remote file_id")

        else:
            # 上传失败
            return Exception("上传失败")

    # 判断文件是否存在,因为fastdfs已经做了文件重名处理
    # 所以即便多次传一个文件也会成功

    def exists(self, name):

        return False


    def url(self, name):
        #name 就是返回的Remote file_id
        #所以我们直接在这里 将图片的完整url 拼接好

        # return "http://192.168.229.133:8888/" + name
        return self.ip + name
